#pragma once
#include <vector>
#include <string.h>
#include <nedmalloc.h>
#include "msg_base.h"
#include "GLog.h"

#define BUFF_SIZE_WARNING 4096
namespace hoyosvr
{
	namespace net
	{
		class read_buffer
		{
		public:
			read_buffer(size_t n)
			{
				_buffer = (char*)nedalloc::nedmalloc(n);
				_post_buff_ptr		= _buffer;
				_data_start_ptr		= _buffer;
				_post_size			= n;
				_is_error			= false;
				_is_reading			= false;
				_new_data_count	= 0;
				_buff_size			= n;
			}
			~read_buffer(void)
			{
				nedalloc::nedfree(_buffer);
			}
			char*	get_post_buffer				()
			{
				_is_reading = true;
				return _post_buff_ptr;
			}
			size_t	get_post_size				()
			{
				if(_post_size < BUFF_SIZE_WARNING)
				{
					LogT <<  "*************** insufficient read buff size:" << _post_size << " *******************" << LogEnd;
				}
				return _post_size;
			}
			bool	has_package					()
			{
				size_t data_len;
				if(_new_data_count > 4)
				{
					int *p = (int*)_data_start_ptr;
					data_len = *p;
					if(_new_data_count >= data_len )
					{
						size_t free_top_buff_size = _data_start_ptr - _buffer;
						if ( free_top_buff_size > _new_data_count )
						{
							memmove(_buffer,_data_start_ptr,_new_data_count);
							_post_buff_ptr = _buffer + _new_data_count;
							_post_size = _buff_size -_new_data_count;
							memset(_post_buff_ptr,0,_post_size);
							_data_start_ptr = _buffer;
						//	LogT <<  "************************************************************\tbuffer move: " << _new_data_count << LogEnd;
						}
						return true;
					}
					else
					{
						if ( data_len > hoyosvr::msg::MAX_MSG_LENGTH )
						{
							_is_error = true;
							if ( data_len != 542393671 && data_len != 1414745936 ) // maybe it is a wired http get or ping , just ignore it
							{
								LogE <<  "data_len error = " << data_len << LogEnd;
							}
							return false;
						}
						
						size_t free_top_buff_size = _data_start_ptr - _buffer;
						if ( free_top_buff_size > _new_data_count )
						{
							memmove(_buffer,_data_start_ptr,_new_data_count);
							_post_buff_ptr = _buffer + _new_data_count;
							_post_size = _buff_size -_new_data_count;
							memset(_post_buff_ptr,0,_post_size);
							_data_start_ptr = _buffer;
							//LogT <<  "************************************************************\tbuffer move: " << _new_data_count << LogEnd;
						}
						return false;
					}
				}			
				return false;
			}
			bool	pop_package					(char** data_ptr,size_t& len)
			{
				len = get_next_length();
				if(len > 0 && len < hoyosvr::msg::MAX_MSG_LENGTH)
				{
					*data_ptr = _data_start_ptr;
					_data_start_ptr += len;
					_new_data_count -= len;
					return true;
				}
				else
				{
					_is_error = true;
					return false;
				}
			}
			void	on_read_data				(size_t len)
			{
				_is_reading			= false;
				_new_data_count += len;
				_post_buff_ptr	+= len;
				_post_size		-= len;
			}
			size_t	get_next_length				()
			{
				if(_new_data_count > 4)
				{
					int *p = (int*)_data_start_ptr;
					int data_len = *p;
					if(data_len < hoyosvr::msg::msg_offset) return 0;
					return data_len;
				}
				return 0;
			}
			bool	is_error					() { return _is_error;}
			bool	is_reading					() { return _is_reading;}
		private:
			
			char*	_buffer;
			size_t	_buff_size;

			char*	_post_buff_ptr;
			char*	_data_start_ptr;

			size_t	_new_data_count;
			size_t	_post_size;
			bool	_is_error;
			bool	_is_reading;
		};
	}
}



